#!/bin/sh
########################################################################
# This script checks if LeakCheck properly handles kasprintf() and 
# kvasprintf(). 
########################################################################

########################################################################
# Checks prerequisites: whether the necessary files exist, etc.
########################################################################
checkPrereqs()
{
    if test ! -f "${TARGET_MODULE}"; then
        printf "Target module is missing: ${TARGET_MODULE}\n"
        exit 1
    fi
    
    if test ! -f "${CONF_FILE}"; then
        printf "KEDR configuration file is missing: ${CONF_FILE}\n"
        exit 1
    fi
}

########################################################################
# Cleanup function (use it if errors occur)
########################################################################
cleanupAll()
{
    lsmod | grep "${TARGET_NAME}" > /dev/null 2>&1
    if test $? -eq 0; then
        rmmod ${TARGET_NAME}
    fi

    sh ${CONTROL_SCRIPT} stop
}

##########################################################################
# Save LeakCheck's report files to the directory specified in $1.
# The directory is cleaned up first
##########################################################################
saveLeakCheckReport()
{
    destDir="$1"
    if test -z "$1"; then
        printf "saveLeakCheckReport(): too few arguments.\n"
        cleanupAll
        exit 1
    fi
    
    rm -rf "${destDir}"
    mkdir -p "${destDir}"
    if test $? -ne 0; then
        printf "Failed to create directory ${destDir} to save LeakCheck's reports to.\n"
        cleanupAll
        exit 1
    fi
    
# Debugfs is kind of a strange file system. It is probably more reliable 
# to use 'cat ... > some_file' than copy the file directly from there.
    cat "${DEBUGFS_LC_DIR}/info" > "${destDir}/info"
    if test $? -ne 0; then
        printf "Failed to copy 'info' file to ${destDir}.\n"
        cleanupAll
        exit 1
    fi
    
    cat "${DEBUGFS_LC_DIR}/possible_leaks" > "${destDir}/possible_leaks"
    if test $? -ne 0; then
        printf "Failed to copy 'possible_leaks' file to ${destDir}.\n"
        cleanupAll
        exit 1
    fi
    
    cat "${DEBUGFS_LC_DIR}/unallocated_frees" > "${destDir}/unallocated_frees"
    if test $? -ne 0; then
        printf "Failed to copy 'unallocated_frees' file to ${destDir}.\n"
        cleanupAll
        exit 1
    fi
}

########################################################################
doTest()
{
    cd "${WORK_DIR}" || exit 1

    reportDir="report_kasprintf"
    
    # Load KEDR core and the payload module, mount debugfs
    sh ${CONTROL_SCRIPT} start ${TARGET_NAME} -f "${CONF_FILE}" || exit 1
    
    insmod "${TARGET_MODULE}"
    if test $? -ne 0; then
        printf "Failed to load the target module\n"
        cleanupAll
        exit 1
    fi
    
    # Check if the necessary files have been created in debugfs
    if test ! -d "${DEBUGFS_LC_DIR}"; then
        printf "Directory for LeakCheck files was not created in debugfs.\n"
        cleanupAll
        exit 1
    fi

    rmmod ${TARGET_NAME}
    if test $? -ne 0; then
        printf "Errors occured while trying to unload the target module\n"
        cleanupAll
        exit 1
    fi

    saveLeakCheckReport "${reportDir}"
    sh ${CONTROL_SCRIPT} stop || exit 1
    
    # Check the report files    
    LC_ALL=C awk -f "${SCRIPT_DIR}/check_summary.awk" \
        -v expectedAllocs=${EXP_ALLOCS_TOTAL} \
        -v expectedLeaks=0 \
        -v expectedBadFrees=0 \
        "${WORK_DIR}/${reportDir}/info"
    if test $? -ne 0; then
        printf "'info' file for the target module contains incorrect data\n"
        # KEDR is already stopped, target is not loaded - no need to 
        # clean up here.
        exit 1
    fi
    
    possibleLeaks=$(cat "${reportDir}/possible_leaks")
    if test $? -ne 0; then
        printf "Failed to open 'possible_leaks' file.\n"
        exit 1
    fi 
    if test -n "${possibleLeaks}"; then
        printf "'possible_leaks' must be empty\n"
        exit 1
    fi

    unallocatedFrees=$(cat "${reportDir}/unallocated_frees")
    if test $? -ne 0; then
        printf "Failed to open 'unallocated_frees' file.\n"
        exit 1
    fi 
    if test -n "${unallocatedFrees}"; then
        printf "'unallocated_frees' must be empty\n"
        exit 1
    fi
}

########################################################################
# main
########################################################################
WORK_DIR="@CMAKE_CURRENT_BINARY_DIR@"
SCRIPT_DIR="@CMAKE_CURRENT_SOURCE_DIR@"

TARGET_NAME="@KEDR_TEST_KASPRINTF_MODULE@"
TARGET_MODULE="${WORK_DIR}/kasprintf_module/${TARGET_NAME}.ko"

CONTROL_SCRIPT="@KEDR_TOOLS_DIR@/control/tests/kedr"
CONF_FILE="${WORK_DIR}/leak_check_test.conf"

DEBUGFS_LC_DIR="@KEDR_TEST_DIR@/debugfs/kedr_leak_check/${TARGET_NAME}"

# Expected number of memory allocations
EXP_ALLOCS_TOTAL=4

checkPrereqs
doTest

# test passed
exit 0
